<template>
<div class="score-analysis-container">
    <!-- 图表卡片 -->
    <el-card class="chart-card">
      <div slot="header" class="chart-header">
        <span class="title">课程成绩分布分析</span>
        <el-tooltip content="箱线图展示各课程成绩分布，红色标记表示成绩差异过小（标准差<3）" placement="top">
          <i class="el-icon-info"></i>
        </el-tooltip>
      </div>
              <div class="filter-group">
          <el-select 
            v-model="selectedSemester"
            @change="handleSemesterChange"
            placeholder="选择学期"
            size="small"
            style="width: 200px; margin-right: 10px;"
          >
            <el-option
              v-for="(semester,index) in semesterOptions"
              :key="index"
              :label="semester"
              :value="semester"
            />
          </el-select>
          <el-select 
            v-model="selectedStdDevFilter"
            @change="handleFilterChange"
            placeholder="标准差筛选"
            size="small"
            style="width: 150px;"
          >
            <el-option
              v-for="item in stdDevOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
          <el-input-number 
            v-model="threshold"
            :min="0.1"
            :max="10"
            :step="0.5"
            :precision="1"
            size="small"
            controls-position="right"
            label="异常阈值"
            style="width: 150px;"
          >
            <template slot="prepend">标准差</template>
          </el-input-number>
        </div>
      <div ref="chart" class="echarts-box"></div>
    </el-card>
<!-- 异常课程提示 -->
    <transition name="el-zoom-in-top">
      <el-alert
        v-if="abnormalCourses.length > 0"
        :title="`异常课程 (共${abnormalCourses.length}门)`"
        type="warning"
        :closable="false"
        class="abnormal-alert"
      >
        <div class="abnormal-list">
          <el-tag 
            v-for="(course, index) in abnormalCourses" 
            :key="index"
            type="warning"
            size="small"
            class="abnormal-tag"
          >
            {{ course }}
          </el-tag>
        </div>
      </el-alert>
    </transition>
  </div>
</template>

<script>
import * as echarts from 'echarts';
import {getFluctuate} from '@/api/student';
import { getSemester } from '@/api/dashboard';

export default {
  data() {
    return {
      threshold: 3, // 默认阈值
      chart: null,
      abnormalCourses: [],
      rawData:[],//api获取数据集

      filteredData: [], // 筛选后的数据

      // 筛选相关数据
      selectedSemester: '2023-2024-1',
      selectedStdDevFilter: 'all',
      semesterOptions: [],
      stdDevOptions: [
        { value: 'all', label: '全部课程' },
        { value: 'abnormal', label: '仅异常课程' },
        { value: 'normal', label: '仅正常课程' }
      ]
    };
  },
  computed: {
    chartSeriesData() {
      return this.filteredData.map(course => {
        // 判断是否为异常课程（标准差<3）
        const isAbnormal = course.stdDev < this.threshold;
        return {
          value: [  // 保持原始数值结构
            course.minScore,
            course.avgScore - course.stdDev,
            course.avgScore,
            course.avgScore + course.stdDev,
            course.maxScore
          ],
          itemStyle: {
            color: isAbnormal ? '#FF6666' : '#5470C6',  // 异常课程红色，正常蓝色
            borderColor: isAbnormal ? '#CC3333' : '#31456B'
          }
        };
      });
    }
  },
  mounted() {
    this.first();
    window.addEventListener('resize', this.handleResize);
  },
  // 在数据为空时显示提示
  watch: {
        // 新增阈值变化监听
    threshold() {
      this.applyFilters();
      this.detectAbnormal();
    },
    rawData(newVal) {
      if (newVal.length === 0) {
        this.$notify.info({
          title: '数据提示',
          message: '当前没有可分析的课程数据',
          duration: 3000
        });
      }
      this.applyFilters();
    }
  },
  methods: {
    first(){
      getSemester().then(res=>{
        this.semesterOptions=res.data
      })
    },
    // 获取后端数据
    async fetchData() {
      try {
        this.$loading({ 
          target: this.$refs.chart,
          text: '正在加载课程数据...',
          background: 'rgba(255,255,255,0.8)'
        });
        const params = {
          semester: this.selectedSemester
        };
        const res = await getFluctuate(params); // 直接 await    后台计算成绩
        console.log('API响应数据:', res);

        // 确保数据结构正确
        if (res && res.data) {
          // 过滤学生数为0的课程
          this.rawData = res.data.filter(course => course.studentCount > 0);
          this.initChart();
          this.detectAbnormal();
        } else {
          throw new Error('响应数据格式错误');
        }
      } catch (error) {
        console.error('数据加载失败:', error);
      } finally {
        this.$loading().close();
      }
    },
    // 应用筛选条件
    applyFilters() {
      this.filteredData = this.rawData.filter(course => {
        // 标准差筛选
        if (this.selectedStdDevFilter === 'abnormal') {
          return course.stdDev < this.threshold;
        }
        if (this.selectedStdDevFilter === 'normal') {
          return course.stdDev >= this.threshold;
        }
        return true;
      });
      
      this.initChart();
      this.detectAbnormal();
    },
     // 学期变更处理
    handleSemesterChange() {
      this.fetchData();
    },

    // 筛选条件变更处理
    handleFilterChange() {
      this.applyFilters();
    },

    // 初始化图表
    initChart() {
      if (this.chart) {
        echarts.dispose(this.chart);
      }

      this.chart = echarts.init(this.$refs.chart);
      const option = {
        title: {
          text: '课程成绩分布箱线图',
          subtext: `共分析 ${this.rawData.length} 门课程`,
          left: 'center',
          textStyle: {
            fontSize: 18,
            color: '#303133'
          },
          subtextStyle: {
            color: '#606266'
          }
        },
        tooltip: {
          trigger: 'item',
          backgroundColor: 'rgba(255,255,255,0.95)',
          borderWidth: 0,
          textStyle: {
            color: '#303133'
          },
          formatter: params => {
            const data = this.filteredData[params.dataIndex];
            return `
              <div style="font-size:14px;color:#409EFF;margin-bottom:8px">
                ${data.courseId || '未命名课程'}（ID:${params.name}）
              </div>
              <div style="line-height:1.8">
                <span style="display:inline-block;width:70px;">最低分</span>：${data.minScore.toFixed(1)}<br>
                <span style="display:inline-block;width:70px;">最高分</span>：${data.maxScore.toFixed(1)}<br>
                <span style="display:inline-block;width:70px;">平均分</span>：<span style="color:#67C23A">${data.avgScore.toFixed(1)}</span><br>
                <span style="display:inline-block;width:70px;">标准差</span>：
                <span style="color:${data.stdDev < this.threshold ?'#F56C6C':'#909399'}">
                  ${data.stdDev.toFixed(2)}
                </span><br>
                <span style="display:inline-block;width:70px;">学生数</span>：${data.studentCount}
              </div>

            `;
          }
        },
        xAxis: {
          type: 'category',
          axisLabel: {
            rotate: 30,
            interval: 0,
            fontSize: 12,
            formatter: value => `ID:${value}` // 更清晰的课程标识
          },
          axisTick: {
            alignWithLabel: true
          }
        },
        yAxis: {
          name: '成绩',
          nameTextStyle: {
            color: '#606266'
          },
          splitLine: {
            lineStyle: {
              type: 'dashed'
            }
          }
        },
        series: [{
          name: '成绩分布',
          type: 'boxplot',
          data: this.chartSeriesData,
          emphasis: {
            itemStyle: {
              borderWidth: 2
            }
          }
        },
          //处理数据  展示平均线
        {
          type: 'line',
          data: this.rawData.map(c => c.avgScore),
          markLine: {
            data: [{ type: 'average' }]
          }
        }
      ],
        dataZoom: [{
          type: 'slider',
          start: 0,
          end: 100,
          bottom: 20
        }]
      };

      this.chart.setOption(option);
    },

    // 检测异常课程（标准差 < 5）   标准差反应的是离散程度    是否存在波动性    成绩减去均值的平方除以  总人数  最后开根号
    detectAbnormal() {
      this.abnormalCourses = this.rawData
        .filter(item => (item.stdDev < this.threshold)&&(item.stdDev > 0))
        .map(item => `课程ID ${item.courseId}（标准差：${item.stdDev.toFixed(1)}）`);
    },

    // 响应式调整
    handleResize() {
      this.chart?.resize();
    }
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.handleResize);
    this.chart?.dispose();
  }
};
</script>

<style scoped>
.score-analysis-container {
  padding: 20px;
  background: #f0f2f5;
  min-height: 100vh;
}

/* 图表卡片 */
.chart-card {
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0,0,0,0.08);
  margin-bottom: 20px;
}

.chart-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid #ebeef5;
}

.title {
  font-size: 18px;
  font-weight: 600;
  color: #303133;
}

.el-icon-info {
  color: #909399;
  cursor: pointer;
  font-size: 18px;
}

/* 图表容器 */
.echarts-box {
  width: 100%;
  height: 600px;
  padding: 20px 0;
}

/* 异常提示 */
.abnormal-alert {
  border-radius: 8px;
  margin-top: 20px;
  transition: all 0.3s;
}

.abnormal-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}

.abnormal-tag {
  font-family: monospace;
  background: rgba(5, 1, 28, 0.1);
  border: 1px solid rgba(233, 237, 236, 0.2);
}
.filter-group {
  display: flex;
  align-items: center;
  gap: 10px; /* 增加间距 */
}

/* 调整输入框前置标签样式 */
.el-input-group__prepend {
  background-color: #fff;
  padding: 0 8px;
  color: #606266;
}
</style>

